package templates;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashMap;

import database.DBUtils;

import pages.InternalErrorException;

public class Template {

	private String templateText = null;
	private HashMap<String, String> changes = new HashMap<String, String>();
	private String[][] menus = new String[10][2];
	private int numOfMenus = 0;

	/**
	 * C`tor that reads the template text from the file
	 * 
	 * @param templateFile
	 * @throws IOException
	 */
	/*
	 * public Template(File templateFile) throws IOException { templateText =
	 * fileGetContents(templateFile); }
	 */

	/**
	 * C`tor that gets the template text directly from the database
	 * 
	 * @param templateText
	 * @throws InternalErrorException
	 */
	public Template(String templateName) throws InternalErrorException {
		String filePath = "../templates/" + templateName + ".template";
		try {
			templateText = fileGetContents(filePath);
			if (templateText == null) {
				throw new InternalErrorException("Can't load template "
						+ templateName);
			}
		} catch (IOException e) {
			throw new InternalErrorException("Can't load template "
					+ templateName + " :", e);
		}

		/*
		 * Connection conn = null; PreparedStatement getTemplateStmt = null;
		 * ResultSet rs = null; try { conn = DBUtils.getConnection();
		 * getTemplateStmt = conn.prepareStatement(
		 * "SELECT `Content` FROM `Templates` WHERE `Name` = ? LIMIT 1;");
		 * getTemplateStmt.setString(1, templateName); rs =
		 * getTemplateStmt.executeQuery(); if (rs.next()) { templateText =
		 * rs.getString("Content"); } else { throw new DBException("Template `"
		 * + templateName + "` is not found"); }
		 * 
		 * } catch (SQLException e) { throw new
		 * DBException("Can't load template " + templateName + " :", e); }
		 * finally { DBUtils.close(rs); DBUtils.close(getTemplateStmt);
		 * DBUtils.close(conn); }
		 */
	}

	/**
	 * Inserts the values into template
	 * 
	 * @param values
	 * @return the string after the changes
	 */
	public String applyValues(HashMap<String, String> values) {
		if (templateText == null) {
			return "";
		}
		if (values == null) {
			return templateText;
		}
		String retText = new String(templateText);
		for (String key : values.keySet()) {
			String value = values.get(key);
			retText = retText.replaceAll("\\[" + key + "\\]", value);
		}
		return retText;
	}

	/**
	 * Stores the change inside
	 * 
	 * @param key
	 * @param value
	 */
	public void addChange(String key, String value) {
		if (key == null || value == null) {
			return;
		}
		changes.put(key, value);
	}

	public String getChange(String key) {
		if (key == null) {
			return null;
		}
		return changes.get(key);
	}

	public void addMenu(String name, String ref) {
		menus[numOfMenus][0] = ref;
		menus[numOfMenus][1] = name;
		numOfMenus++;
	}

	/**
	 * Inserts all the inside changes to the template
	 * 
	 * @return
	 */
	public String applyChanges() {
		return applyValues(changes);
	}

	public String createMenus(String userLogin) {
		String userRole = getUserRole(userLogin);
		String menuData = "";
		
		if(userRole != null)
		{
			boolean isUser = false;
			if (userRole.compareTo("RESEARCHER") == 0)
				isUser = true;
			else
				isUser = false;
			if(isUser)
			{
				addMenu("My Details", "users/UserInfo");
				addMenu("My Reservations", "users/ViewReservations");
				addMenu("Add Reservation", "users/AddResevation");
			}
			else
			{
				addMenu("Users", "admins/UsersList");
				addMenu("Instruments", "admins/InstrumentsList");
				addMenu("Reservations", "admins/ReservationsList");
				addMenu("Add XSL", "admins/AddXSL");
				
			
				
			}
		}
		for (int i = 0; i < numOfMenus; i++) {
			menuData += "\t\t\t\t\t<li><a href=\"/severandstemka/"
					+ menus[i][0] + "\" class=\"link2\">" + menus[i][1]
					+ "</a></li>\n";
		}
		return menuData;
	}
	
	private String getUserRole(String username)
	{
		Connection conn = null;
		PreparedStatement selectUserStmt = null;
		ResultSet rs = null;
		try {
			conn = DBUtils.getConnection();
			selectUserStmt = conn.prepareStatement("select role from roles where login=?;");
			selectUserStmt.setString(1, username);
			rs = selectUserStmt.executeQuery();
			if (rs == null || !rs.next()) {
				return null;
			} else {
				return rs.getString("role");

			}
		} catch (Exception e) {
			return null;
		} finally {
			DBUtils.close(rs);
			DBUtils.close(selectUserStmt);
			DBUtils.close(conn);
		}	
	}

	/**
	 * Applies the changes and wraps the template with LM-page
	 * 
	 * @param pageTitle
	 * @return the whole page
	 * @throws DBException
	 */
	public String createPage(String pageTitle, String userLogin)
			throws InternalErrorException {
		return wrapWithPage(applyChanges(), createMenus(userLogin), pageTitle, userLogin);
	}

	/**
	 * Wraps the text with the global page
	 * 
	 * @param text
	 * @return String containing LM-page with the text
	 * @throws IOException
	 */
	public static String wrapWithPage(String text, String menuData,
			String title, String userLogin) throws InternalErrorException {
		Template pageTemplate = new Template("page");

		if (userLogin == null) {
			pageTemplate.addChange("registerLogoutLink", "Register");
			pageTemplate.addChange("registerLogoutText", "Register");
		} else {
			pageTemplate.addChange("registerLogoutLink", "Logout");
			pageTemplate.addChange("registerLogoutText", "Logout");

		}

		pageTemplate.addChange("page", text);
		pageTemplate.addChange("menu", menuData);
		pageTemplate.addChange("title", title);
		return pageTemplate.applyChanges();
	}

	private String fileGetContents(String filePath) throws IOException {
		InputStream templateStream = Template.class
				.getResourceAsStream(filePath);
		return convertStreamToString(templateStream);

	}

	private String convertStreamToString(InputStream is) throws IOException {
		/*
		 * To convert the InputStream to String we use the
		 * BufferedReader.readLine() method. We iterate until the BufferedReader
		 * return null which means there's no more data to read. Each line will
		 * appended to a StringBuilder and returned as String.
		 */
		if (is != null) {
			StringBuilder sb = new StringBuilder();
			String line;

			try {
				BufferedReader reader = new BufferedReader(
						new InputStreamReader(is, "UTF-8"));
				while ((line = reader.readLine()) != null) {
					sb.append(line).append("\n");
				}
			} finally {
				is.close();
			}
			return sb.toString();
		} else {
			return null;
		}
	}
}
